[レポート]Pwn2Ownのターゲットをハッキングした3年間の物語:攻撃、ベンダーの進化、そして教訓 – CODE BLUE 2023 #codeblue_jp
こんにちは、臼田です。
みなさん、セキュリティ対策してますか?(挨拶
今回はCODE BLUE 2023で行われた以下のセッションのレポートです。
Pwn2Ownのターゲットをハッキングした3年間の物語:攻撃、ベンダーの進化、そして教訓
現代生活に欠かせないスマートスピーカーは、ホーム・オートメーション・システム(スマートホームシステム)において重要な役割を担っている。この分野のリーディングカンパニーとして台頭してきたSonosは、セキュリティを優先した結果、Sonos One Speakerが3年連続でPwn2Own(CanSecWest主催のコンピューター・ハッキング・コンテスト)のターゲットとなった。ハッキングに成功した最初のチームとして、過去3年間の研究を通しての経験、ストーリー、知見を共有する。この講演では、ハードウェア、ファームウェア、ソフトウェアの各レイヤーにおける攻撃を探るとともに、われわれが観察したSonosの防御機構の進化(変遷)についても解説を行う。また、われわれがSonosのセキュリティ・チームと行った「いたちごっこ(cat-and-mouse game)」についても触れるつもりだ。 なぜSonosのセキュリティ・チームは、毎回われわれが実用的なエクスプロイトを開発した直後に、その脆弱性を正確に修正することができたのだろうか?そのため、Pwn2Ownの1つのターゲットを攻略するために、4つの異なる種別のゼロデイ脆弱性を使うことになった。 このプロジェクトでは、1年目のわれわれの面白くも失敗した挑戦から始まり、2年目には整数アンダーフローを使用してターゲットの乗っ取りに成功しました。Pwn2Ownの後、われわれはSonosの防御機構が大きく飛躍したことを目の当たりにし、3年目にはSonosのセキュリティ・チームとの闘いがさらに困難なものになった。われわれの研究の全体像を共有するため、本発表では、DMA(Direct Memory Access)攻撃を活用して脱獄しローカルシェルを取得するなどのハードウェア攻撃、ファームウェアの復号からファームウェアアップデート機構における脆弱性の発見に至るファームウェア分析、そしてソフトウェアレベルのアタックサーフェス分析やさまざまな脆弱性発見手法を取り上げる。すべての保護機構をバイパスしてターゲットをエクスプロイトすること、スレッドのスタックを異なるプリミティブに競合させて発生するスタック破壊を悪用してエクスプロイトすること、さまざまな種類の脆弱性を利用してRCE(Remote Code Execution)を達成することなど、エクスプロイト成功の背後にあるストーリーを詳説する。これによりわれわれはPwn2Own Toronto 2022で優勝し、80,000ドル以上の報酬を獲得した。
Presented by : オレンジ・ツァイ - Orange Tsai
レポート
- この長いタイトルの話をします
- 今日は新しい取り組みをする
- ショーケースをしてみたい
- 過去どういうことを試みたか
- 失敗も含めて話す
- 皆さんのハッキングの参考になると考えている
- 私にとってはワークスペースの整理をする意味もある
- こういう状況になった人がいるのではないか
- test.pyとか色々ごちゃごちゃ並んでいる状況
- 自己紹介
- DEVCOREで活動している
- いろんな賞をもらっている
- Sonosにフォーカスした
- なぜ?
- 別のことをしてみたいと思った
- Pwn2Ownで解読されていないものを対象にしてみた
- 2020年に残り2週間で取り組み始めた
- 物理的なものを持っていなかった
- webでブラックボックスで調査を始めた
- ファームウェアを探した
- WebデバッグとUPnPからアプローチ
- デバッグモード
- 凄くシンプルな画面
- しかしシンプルなバグはなかった
- コマンドインジェクションをためした
- 効果はなかった
- SoCoというものがあった
- urlから音楽を再生したりできる
- Sonosはインターネット上のユーザーを信頼する
- FWがなく、だれかのボリュームをMAXにできる
- SOAPでできる
- UAがwgetで通信されることを確認した
- インターネットでファームを見つけたが古く陳腐化されていた
- 新しいものはbinwalkで読めなかった
- 2年前のバイナリを得てリバースしてみた
- webサーバがバイナリアップデートを行って、コンテンツをstdoutに分類する
- いくつかのURLを使って攻撃を試みた
- SSRFしたがいい攻撃対象が見つからなかった
- Wgetの脆弱性を活用してみようとしたができなかった
- ファーム攻撃を開発してバックドアやダウングレードも試みたがRSAを使ってハッシュもつかってそれぞれ保護していた
- もしこのハッシュを解読できたら教えてくれ(スライドに表示)
- 来年のPow2Ownで賞を分け合いましょう
- ファームウェアパーサーでBOFを見つけた
- しかしうまく使えなかった
- 2020年のまとめ
- 2018年のファームは入手したが2020年のものでは攻撃できなかった
- 改善すべきことはリバースエンジニアリングを早くすること
- 2021年の話
- なぜSonosを再びターゲットにしたのか
- 負け犬のような気持ちになった
- ハードウェア攻撃についての記事が出ていた
- 機器を早めに購入して3ヶ月使って準備した
- ハードはUSB3380 Evaluation Board
- リセラーの一人が台湾ベースだった
- お金を払って24時間以内に入手できた
- しかしハードウェアについては素人で理解できなかった
- まずプラグしたのに使えなかった
- 1週間うまく行かなかった
- GitHubのIssueを見つけた
- デフォルトで使えない
- ファームウェアをフラッシュしないといけないことがわかった
- アダプタをまず見つける
- これも難しかった
- ほとんどの新しいデバイスでは使われていない
- M.2スロットしか見つからない
- Mini PCIeはあまり使われていない
- ThinkPadをかりてWiFiデバイスを外してようやくプラグイン
- しかしThinkPadにはホワイトリストでデバイスが使えなかった
- BIOSのJailbreakする必要がある
- ローカルシェルを使ってバイナリを取得
- system(3)やexec*(3)などを確認した
- しかしバグは見つからなかった
- 失敗が続いてそろそろ自分の頭を使ったほうがいいと思った
- Sonosは音楽デバイスでオープンソースのライブラリが使われている
- どのようにSonosがメタデータを扱っているのかを気にし始めた
- 全てがマニュアルかもしれない
- ハンドメイドのコードを読む方が彼らのコーディングを理解できる
- 最初のバグ
- パースするところの問題
- バッファがx0D0だった
- しかしどんなに頑張ってもクラッシュしなかった
- 2回目のreadの前に増やしていた
- alloca関数でダイナミックスタックの割当がされていた
- 最初のフェイクバグだった
- なぜSonosを再びターゲットにしたのか
- 典型的なリサーチャーの期待マップ
- バグがないと思って萎える
- もしかしてバグが有るって思ってアガる
- バグじゃなくてまた萎える
- しかしシステムについて理解できている
- これは必要な過程
- ホントのバグを発見
- ID3v2タグのところ
- フレームサイズでフレームデータの長さが入っている
- フレームサイズのチェックなしで小さくしている
- underflowがあった
- 到達は簡単ではない
- 到達したら簡単、猫でもできる
- PIEとcanaryはない
- ROPを使えば簡単
- 2年目の教訓
- いいアタックサーフェイスを見つけたら簡単になる
- 無駄な時間を過ごした
- 盲目的な試行錯誤は意味がない
- 基本を理解することに時間をかけるべき
- ファジングを早く諦めすぎた
- まずマニュアルを読もう
- 2022年
- なぜまた同じターゲットなのか
- お金に目がくらんだ
- 60K USDを獲得できた
- 同じやり方で稼ぎたかった
- しかし全く楽ではなかった
- 3ヶ月まるまる時間を使った
- 友人とHITCONであった時の話
- Sonosが全てのバイナリプロテクションを実装したって知ってる?
- まじかよ!
- まず昨年のアタックサーフェイスを深掘りしてみた
- 今回はMP3がMP4になっていた
- Boxにメタデータが保存されている
- ftypの調査
- box_sizeを使ってallocaしている
- これのほうがエクスプロイトしやすそう
- Return Addressとローカル変数
- カナリがその上にあり、バッファは近いところにある
- もう少し全体をみる
- マルチスレッドなので各スレッドでスタックがある
- 現在のスタックから遠くにジャンプできないか
- 別のスレッドのスタックをOverflowできないか
- これをStack Clashバグと命名した
- 詳細は省略する
- 書き込む瞬間が重要で、しっかりやらないとクラッシュする
- gethostbyname_r(3)を利用して動いている
- DNSを自分たちでホストしてレスポンスを遅らせるといけるのでは
- ベースアドレスのリークができた
- すべての保護をバイパスしてエクスプロイトできた
- 9/19にその内容をチームに報告した
- 9/20にSonosがパッチでそれを修正した
- 先程のリサーチャーの期待マップ
- サイレントに修正されることで一番さがった
- どうするか
- 別のアタックサーフェイスを見つけるしか無い
- オープンソースのインテグレーションについて確認した
- Glueコードが必要になる
- インテグレータがきちんと理解していない場合に間違いが起きる
- SonosはXMLを利用しているのでXMLパーサに着目
- libexpat
- ライブラリの使い方はどうか
- 対応するcallbackを書かないといけない
- callbackにバグが見つかるかも
- 実際のコードを見てみる
- blockタグではmalloc
- blockがいくつかのparamとペアリングされている
- 繰り返し全てのブロックを利用していた
- OOB-Write
- いろいろ克服して任意でWriteできるようになった
- しかし全ての保護機能が有効化されている
- どこにWriteするのか、確認する必要があった
- OverSiteバグをみつけた
- SSDPブロードキャスティングの例
- パケットサイズを直接利用していた
- これがリークに繋がった
- そして、Sonosはまたアップデートしてきた
- 修正された
- アーキテクチャの大きな変更が行われたらしい
- このタイミングは偶然としてはおかしいのでは?
- Sonosがcrashdumpの解析を始めたのではないか
- 1ヶ月残っているので大丈夫だと思った
- 全然だめだった
- これまでのバグを再確認してみた
- 興味深いバグを見つけた
- フェイクバグについて
- アーキテクチャの変更によってフェイクバグが本物のバグになった
- バッファが固定サイズになっている
- 255byteまで書き込める
- 今回は忘れずにケーブルを切っておきました
- 3年目の振り返り
- バイナリ関連のバグのカバレッジ
- アタックサーフェイスの振り返り
- libsmb2を見なかった
- crashdumpを取られないためにラボ環境の整備が必要
- まとめ
- 情熱が必要
- 同じことに長く取り組む
- 最後まで粘り強く取り組まなければいけない
- 正しい道筋(アタックサーフェイス)である必要がある
- 今回のバグの半分はアタックサーフェイスの選定が良かった
- ゲームのCelesteから言葉を引用する
- 死んだ数が大切である
- 情熱が必要
感想
成功の裏側にはたくさんの失敗があることがよく分かる話でした。
私もCelesteでは山程屍を重ねています。筋の良いところで、失敗を積み重ねていきたいですね。